{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "389f9c5c-553b-48ab-ad34-1acc19416e30",
   "metadata": {},
   "source": [
    "# LangChain Tool calling capabilities with Unity Catalog\n",
    "\n",
    "## Prerequisites\n",
    "\n",
    "**API Key**\n",
    "To run this tutorial, you will need an OpenAI API key. \n",
    "\n",
    "Once you have acquired your key, set it to the environment variable `OPENAI_API_KEY`.\n",
    "\n",
    "Below, we validate that this key is set properly in your environment.\n",
    "\n",
    "**Packages**\n",
    "\n",
    "To interface with both UnityCatalog and LangChain, you will need to install the following packages:\n",
    "\n",
    "```shell\n",
    "pip install langchain_openai unitycatalog-langchain\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "830b8bc0-fe93-4241-8411-519148095e7e",
   "metadata": {},
   "outputs": [],
   "source": [
    "import os\n",
    "\n",
    "assert \"OPENAI_API_KEY\" in os.environ, (\n",
    "    \"Please set the OPENAI_API_KEY environment variable to your OpenAI API key\"\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a637813f-d5e7-4b0f-9ca6-1befa9af9994",
   "metadata": {},
   "source": [
    "## Configuration and Client setup\n",
    "\n",
    "In order to connect to your Unity Catalog server, you'll need an instance of the `ApiClient` from the `unitycatalog-client` package. \n",
    "\n",
    "> Note: If you don't already have a Catalog and a Schema created, be sure to create them before running this notebook and adjust the `CATALOG` and `SCHEMA` variables below to suit."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b17c5e1d-7f44-4cfe-a9e2-fa9243afda1f",
   "metadata": {},
   "outputs": [],
   "source": [
    "from unitycatalog.ai.core.client import UnitycatalogFunctionClient\n",
    "from unitycatalog.ai.langchain.toolkit import UCFunctionToolkit\n",
    "from unitycatalog.client import ApiClient, Configuration"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f65129d5-e37d-42d0-8da6-47013487d82b",
   "metadata": {},
   "outputs": [],
   "source": [
    "config = Configuration(host=\"http://localhost:8080/api/2.1/unity-catalog\")\n",
    "\n",
    "api_client = ApiClient(configuration=config)\n",
    "\n",
    "client = UnitycatalogFunctionClient(api_client=api_client)\n",
    "\n",
    "CATALOG = \"AICatalog\"\n",
    "SCHEMA = \"AISchema\""
   ]
  },
  {
   "cell_type": "markdown",
   "id": "16f09d55-664c-4ac6-92a6-27a0cde9a77f",
   "metadata": {},
   "source": [
    "## Define functions and register them to Unity Catalog\n",
    "\n",
    "In this next section, we'll be defining two Python functions and creating them within Unity Catalog so that they can be retrieved and used as tools within our LangChain Agent. \n",
    "\n",
    "There are a few things to keep in mind when creating functions for use with the `create_python_function` API:\n",
    "\n",
    "- Ensure that your have properly defined types for all arguments and for the return of the function.\n",
    "- Ensure that you have a Google-style docstring defined that includes descriptions for the function, each argument, and the return of the function. This is critical, as these are used to populate the metadata associated with the function within Unity Catalog, providing contextual data for an LLM to understand when and how to call the tool associated with this function.\n",
    "- If there are packages being called that are not part of core Python, ensure that the import statements are locally scoped (defined within the function body)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "37ba63c9-2038-4c92-98ab-e938577ebd62",
   "metadata": {},
   "outputs": [],
   "source": [
    "def calculate_required_laser_power(\n",
    "    material: str, thickness: float, cutting_speed: float, laser_efficiency: float = 0.8\n",
    ") -> float:\n",
    "    \"\"\"\n",
    "    Calculates the minimum laser power required to cut through a specific material.\n",
    "\n",
    "    The required laser power is determined based on the material's thermal properties,\n",
    "    thickness, and the desired cutting speed. The formula used is:\n",
    "\n",
    "        P = (k * thickness * cutting_speed) / (η * A)\n",
    "\n",
    "    where:\n",
    "        - P is the required laser power (W).\n",
    "        - k is the thermal conductivity of the material (W/m·K).\n",
    "        - thickness is the material thickness (m).\n",
    "        - cutting_speed is the speed at which the laser moves (m/s).\n",
    "        - η is the laser efficiency (dimensionless).\n",
    "        - A is the absorption coefficient of the material (dimensionless, between 0 and 1).\n",
    "\n",
    "    Args:\n",
    "        material (str): Type of the material (e.g., 'steel', 'aluminum', 'copper').\n",
    "        thickness (float): Thickness of the material in meters (m).\n",
    "        cutting_speed (float): Desired cutting speed in meters per second (m/s).\n",
    "        laser_efficiency (float, optional): Efficiency of the laser system (default is 0.8).\n",
    "\n",
    "    Returns:\n",
    "        Required laser power in watts (W).\n",
    "    \"\"\"\n",
    "\n",
    "    material_properties = {\n",
    "        \"steel\": {\"thermal_conductivity\": 50, \"absorption_coefficient\": 0.5},\n",
    "        \"aluminum\": {\"thermal_conductivity\": 205, \"absorption_coefficient\": 0.6},\n",
    "        \"copper\": {\"thermal_conductivity\": 385, \"absorption_coefficient\": 0.55},\n",
    "        \"titanium\": {\"thermal_conductivity\": 22, \"absorption_coefficient\": 0.45},\n",
    "        \"brass\": {\"thermal_conductivity\": 110, \"absorption_coefficient\": 0.5},\n",
    "        \"polycarbonate\": {\"thermal_conductivity\": 0.2, \"absorption_coefficient\": 0.3},\n",
    "        \"acrylic\": {\"thermal_conductivity\": 0.2, \"absorption_coefficient\": 0.35},\n",
    "    }\n",
    "\n",
    "    if material.lower() not in material_properties:\n",
    "        raise ValueError(\n",
    "            f\"Unsupported material: {material}. Supported materials are: {list(material_properties.keys())}\"\n",
    "        )\n",
    "\n",
    "    if thickness <= 0:\n",
    "        raise ValueError(\"Thickness must be a positive value.\")\n",
    "    if cutting_speed <= 0:\n",
    "        raise ValueError(\"Cutting speed must be a positive value.\")\n",
    "    if not (0 < laser_efficiency <= 1):\n",
    "        raise ValueError(\"Laser efficiency must be between 0 (exclusive) and 1 (inclusive).\")\n",
    "\n",
    "    properties = material_properties[material.lower()]\n",
    "    k = properties[\"thermal_conductivity\"]  # W/m·K\n",
    "    A = properties[\"absorption_coefficient\"]  # Dimensionless\n",
    "\n",
    "    power = (k * thickness * cutting_speed) / (laser_efficiency * A)\n",
    "\n",
    "    return power\n",
    "\n",
    "\n",
    "def calculate_cutting_speed(\n",
    "    material: str, thickness: float, laser_power: float, laser_efficiency: float = 0.8\n",
    ") -> float:\n",
    "    \"\"\"\n",
    "    Calculates the maximum cutting speed achievable with a given laser power.\n",
    "\n",
    "    The cutting speed is determined based on the material's thermal properties,\n",
    "    thickness, and the available laser power. The formula used is:\n",
    "\n",
    "        cutting_speed = (P * η * A) / (k * thickness)\n",
    "\n",
    "    where:\n",
    "        - P is the laser power (W).\n",
    "        - η is the laser efficiency (dimensionless).\n",
    "        - A is the absorption coefficient of the material (dimensionless, between 0 and 1).\n",
    "        - k is the thermal conductivity of the material (W/m·K).\n",
    "        - thickness is the material thickness (m).\n",
    "\n",
    "    Args:\n",
    "        material (str): Type of the material (e.g., 'steel', 'aluminum', 'copper').\n",
    "        thickness (float): Thickness of the material in meters (m).\n",
    "        laser_power (float): Available laser power in watts (W).\n",
    "        laser_efficiency (float, optional): Efficiency of the laser system (default is 0.8).\n",
    "\n",
    "    Returns:\n",
    "        Maximum cutting speed in meters per second (m/s).\n",
    "    \"\"\"\n",
    "    material_properties = {\n",
    "        \"steel\": {\"thermal_conductivity\": 50, \"absorption_coefficient\": 0.5},\n",
    "        \"aluminum\": {\"thermal_conductivity\": 205, \"absorption_coefficient\": 0.6},\n",
    "        \"copper\": {\"thermal_conductivity\": 385, \"absorption_coefficient\": 0.55},\n",
    "        \"titanium\": {\"thermal_conductivity\": 22, \"absorption_coefficient\": 0.45},\n",
    "        \"brass\": {\"thermal_conductivity\": 110, \"absorption_coefficient\": 0.5},\n",
    "        \"polycarbonate\": {\"thermal_conductivity\": 0.2, \"absorption_coefficient\": 0.3},\n",
    "        \"acrylic\": {\"thermal_conductivity\": 0.2, \"absorption_coefficient\": 0.35},\n",
    "    }\n",
    "\n",
    "    if material.lower() not in material_properties:\n",
    "        raise ValueError(\n",
    "            f\"Unsupported material: {material}. Supported materials are: {list(material_properties.keys())}\"\n",
    "        )\n",
    "\n",
    "    if thickness <= 0:\n",
    "        raise ValueError(\"Thickness must be a positive value.\")\n",
    "    if laser_power <= 0:\n",
    "        raise ValueError(\"Laser power must be a positive value.\")\n",
    "    if not (0 < laser_efficiency <= 1):\n",
    "        raise ValueError(\"Laser efficiency must be between 0 (exclusive) and 1 (inclusive).\")\n",
    "\n",
    "    properties = material_properties[material.lower()]\n",
    "    k = properties[\"thermal_conductivity\"]\n",
    "    A = properties[\"absorption_coefficient\"]\n",
    "\n",
    "    speed = (laser_power * laser_efficiency * A) / (k * thickness)\n",
    "\n",
    "    return speed"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "33dcd9ab-1d8e-4392-8249-e4872bbf7888",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "FunctionInfo(name='calculate_required_laser_power', catalog_name='AICatalog', schema_name='AISchema', input_params=FunctionParameterInfos(parameters=[FunctionParameterInfo(name='material', type_text='STRING', type_json='{\"name\": \"material\", \"type\": \"string\", \"nullable\": false, \"metadata\": {\"comment\": \"Type of the material (e.g., \\\\\"steel\\\\\", \\\\\"aluminum\\\\\", \\\\\"copper\\\\\").\"}}', type_name=<ColumnTypeName.STRING: 'STRING'>, type_precision=None, type_scale=None, type_interval_type=None, position=0, parameter_mode=None, parameter_type=None, parameter_default=None, comment='Type of the material (e.g., \"steel\", \"aluminum\", \"copper\").'), FunctionParameterInfo(name='thickness', type_text='DOUBLE', type_json='{\"name\": \"thickness\", \"type\": \"double\", \"nullable\": false, \"metadata\": {\"comment\": \"Thickness of the material in meters (m).\"}}', type_name=<ColumnTypeName.DOUBLE: 'DOUBLE'>, type_precision=None, type_scale=None, type_interval_type=None, position=1, parameter_mode=None, parameter_type=None, parameter_default=None, comment='Thickness of the material in meters (m).'), FunctionParameterInfo(name='cutting_speed', type_text='DOUBLE', type_json='{\"name\": \"cutting_speed\", \"type\": \"double\", \"nullable\": false, \"metadata\": {\"comment\": \"Desired cutting speed in meters per second (m/s).\"}}', type_name=<ColumnTypeName.DOUBLE: 'DOUBLE'>, type_precision=None, type_scale=None, type_interval_type=None, position=2, parameter_mode=None, parameter_type=None, parameter_default=None, comment='Desired cutting speed in meters per second (m/s).'), FunctionParameterInfo(name='laser_efficiency', type_text='DOUBLE', type_json='{\"name\": \"laser_efficiency\", \"type\": \"double\", \"nullable\": true, \"metadata\": {\"comment\": \"Efficiency of the laser system (default is 0.8).\"}}', type_name=<ColumnTypeName.DOUBLE: 'DOUBLE'>, type_precision=None, type_scale=None, type_interval_type=None, position=3, parameter_mode=None, parameter_type=None, parameter_default='0.8', comment='Efficiency of the laser system (default is 0.8).')]), data_type=<ColumnTypeName.DOUBLE: 'DOUBLE'>, full_data_type='DOUBLE', return_params=None, routine_body='EXTERNAL', routine_definition='import math  # local imports are neeeded for Unity Catalog functions\\n\\nmaterial_properties = {\\n    \\'steel\\': {\\'thermal_conductivity\\': 50, \\'absorption_coefficient\\': 0.5},\\n    \\'aluminum\\': {\\'thermal_conductivity\\': 205, \\'absorption_coefficient\\': 0.6},\\n    \\'copper\\': {\\'thermal_conductivity\\': 385, \\'absorption_coefficient\\': 0.55},\\n    \\'titanium\\': {\\'thermal_conductivity\\': 22, \\'absorption_coefficient\\': 0.45},\\n    \\'brass\\': {\\'thermal_conductivity\\': 110, \\'absorption_coefficient\\': 0.5},\\n    \\'polycarbonate\\': {\\'thermal_conductivity\\': 0.2, \\'absorption_coefficient\\': 0.3},\\n    \\'acrylic\\': {\\'thermal_conductivity\\': 0.2, \\'absorption_coefficient\\': 0.35},\\n}\\n\\nif material.lower() not in material_properties:\\n    raise ValueError(f\"Unsupported material: {material}. Supported materials are: {list(material_properties.keys())}\")\\n\\nif thickness <= 0:\\n    raise ValueError(\"Thickness must be a positive value.\")\\nif cutting_speed <= 0:\\n    raise ValueError(\"Cutting speed must be a positive value.\")\\nif not (0 < laser_efficiency <= 1):\\n    raise ValueError(\"Laser efficiency must be between 0 (exclusive) and 1 (inclusive).\")\\n\\nproperties = material_properties[material.lower()]\\nk = properties[\\'thermal_conductivity\\']  # W/m·K\\nA = properties[\\'absorption_coefficient\\']  # Dimensionless\\n\\npower = (k * thickness * cutting_speed) / (laser_efficiency * A)\\n\\nreturn power', routine_dependencies=None, parameter_style='S', is_deterministic=True, sql_data_access='NO_SQL', is_null_call=False, security_type='DEFINER', specific_name='calculate_required_laser_power', comment=\"Calculates the minimum laser power required to cut through a specific material. The required laser power is determined based on the material's thermal properties, thickness, and the desired cutting speed. The formula used is: P = (k * thickness * cutting_speed) / (η * A) where: - P is the required laser power (W). - k is the thermal conductivity of the material (W/m·K). - thickness is the material thickness (m). - cutting_speed is the speed at which the laser moves (m/s). - η is the laser efficiency (dimensionless). - A is the absorption coefficient of the material (dimensionless, between 0 and 1).\", properties='null', full_name='AICatalog.AISchema.calculate_required_laser_power', owner=None, created_at=1732658127404, created_by=None, updated_at=1732658127404, updated_by=None, function_id='80dc1669-0a2e-4b90-84b5-fabb680fdac3', external_language='PYTHON')"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "client.create_python_function(\n",
    "    func=calculate_required_laser_power, catalog=CATALOG, schema=SCHEMA, replace=True\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "df2a408b-e9a0-4e00-af97-e1072f8a9336",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "FunctionInfo(name='calculate_cutting_speed', catalog_name='AICatalog', schema_name='AISchema', input_params=FunctionParameterInfos(parameters=[FunctionParameterInfo(name='material', type_text='STRING', type_json='{\"name\": \"material\", \"type\": \"string\", \"nullable\": false, \"metadata\": {\"comment\": \"Type of the material (e.g., \\\\\"steel\\\\\", \\\\\"aluminum\\\\\", \\\\\"copper\\\\\").\"}}', type_name=<ColumnTypeName.STRING: 'STRING'>, type_precision=None, type_scale=None, type_interval_type=None, position=0, parameter_mode=None, parameter_type=None, parameter_default=None, comment='Type of the material (e.g., \"steel\", \"aluminum\", \"copper\").'), FunctionParameterInfo(name='thickness', type_text='DOUBLE', type_json='{\"name\": \"thickness\", \"type\": \"double\", \"nullable\": false, \"metadata\": {\"comment\": \"Thickness of the material in meters (m).\"}}', type_name=<ColumnTypeName.DOUBLE: 'DOUBLE'>, type_precision=None, type_scale=None, type_interval_type=None, position=1, parameter_mode=None, parameter_type=None, parameter_default=None, comment='Thickness of the material in meters (m).'), FunctionParameterInfo(name='laser_power', type_text='DOUBLE', type_json='{\"name\": \"laser_power\", \"type\": \"double\", \"nullable\": false, \"metadata\": {\"comment\": \"Available laser power in watts (W).\"}}', type_name=<ColumnTypeName.DOUBLE: 'DOUBLE'>, type_precision=None, type_scale=None, type_interval_type=None, position=2, parameter_mode=None, parameter_type=None, parameter_default=None, comment='Available laser power in watts (W).'), FunctionParameterInfo(name='laser_efficiency', type_text='DOUBLE', type_json='{\"name\": \"laser_efficiency\", \"type\": \"double\", \"nullable\": true, \"metadata\": {\"comment\": \"Efficiency of the laser system (default is 0.8).\"}}', type_name=<ColumnTypeName.DOUBLE: 'DOUBLE'>, type_precision=None, type_scale=None, type_interval_type=None, position=3, parameter_mode=None, parameter_type=None, parameter_default='0.8', comment='Efficiency of the laser system (default is 0.8).')]), data_type=<ColumnTypeName.DOUBLE: 'DOUBLE'>, full_data_type='DOUBLE', return_params=None, routine_body='EXTERNAL', routine_definition='material_properties = {\\n    \\'steel\\': {\\'thermal_conductivity\\': 50, \\'absorption_coefficient\\': 0.5},\\n    \\'aluminum\\': {\\'thermal_conductivity\\': 205, \\'absorption_coefficient\\': 0.6},\\n    \\'copper\\': {\\'thermal_conductivity\\': 385, \\'absorption_coefficient\\': 0.55},\\n    \\'titanium\\': {\\'thermal_conductivity\\': 22, \\'absorption_coefficient\\': 0.45},\\n    \\'brass\\': {\\'thermal_conductivity\\': 110, \\'absorption_coefficient\\': 0.5},\\n    \\'polycarbonate\\': {\\'thermal_conductivity\\': 0.2, \\'absorption_coefficient\\': 0.3},\\n    \\'acrylic\\': {\\'thermal_conductivity\\': 0.2, \\'absorption_coefficient\\': 0.35},\\n}\\n\\nif material.lower() not in material_properties:\\n    raise ValueError(f\"Unsupported material: {material}. Supported materials are: {list(material_properties.keys())}\")\\n\\nif thickness <= 0:\\n    raise ValueError(\"Thickness must be a positive value.\")\\nif laser_power <= 0:\\n    raise ValueError(\"Laser power must be a positive value.\")\\nif not (0 < laser_efficiency <= 1):\\n    raise ValueError(\"Laser efficiency must be between 0 (exclusive) and 1 (inclusive).\")\\n\\nproperties = material_properties[material.lower()]\\nk = properties[\\'thermal_conductivity\\']\\nA = properties[\\'absorption_coefficient\\']\\n\\nspeed = (laser_power * laser_efficiency * A) / (k * thickness)\\n\\nreturn speed', routine_dependencies=None, parameter_style='S', is_deterministic=True, sql_data_access='NO_SQL', is_null_call=False, security_type='DEFINER', specific_name='calculate_cutting_speed', comment=\"Calculates the maximum cutting speed achievable with a given laser power. The cutting speed is determined based on the material's thermal properties, thickness, and the available laser power. The formula used is: cutting_speed = (P * η * A) / (k * thickness) where: - P is the laser power (W). - η is the laser efficiency (dimensionless). - A is the absorption coefficient of the material (dimensionless, between 0 and 1). - k is the thermal conductivity of the material (W/m·K). - thickness is the material thickness (m).\", properties='null', full_name='AICatalog.AISchema.calculate_cutting_speed', owner=None, created_at=1732658127799, created_by=None, updated_at=1732658127799, updated_by=None, function_id='2fd9e1b6-a7c5-4641-86b6-cfb3190bf779', external_language='PYTHON')"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "client.create_python_function(\n",
    "    func=calculate_cutting_speed, catalog=CATALOG, schema=SCHEMA, replace=True\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "266576ca-12a5-4f44-8a80-f9fa18f6ff95",
   "metadata": {},
   "source": [
    "## Create a Toolkit instance of the functions\n",
    "\n",
    "Now that the functions have been created within Unity Catalog, we can use the `unitycatalog-langchain` package to create a toolkit instance that our Agent will 'understand' as valid tools to use within its APIs. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "6aad4bf9-d450-480a-a109-d9e4a0da901a",
   "metadata": {},
   "outputs": [],
   "source": [
    "laser_power_func = f\"{CATALOG}.{SCHEMA}.calculate_required_laser_power\"\n",
    "cutting_speed_func = f\"{CATALOG}.{SCHEMA}.calculate_cutting_speed\"\n",
    "\n",
    "toolkit = UCFunctionToolkit(function_names=[laser_power_func, cutting_speed_func], client=client)\n",
    "\n",
    "tools = toolkit.tools"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "32392ed7-6e41-4377-8760-53448f5bf30f",
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain.agents import AgentExecutor, create_tool_calling_agent\n",
    "from langchain_core.prompts import ChatPromptTemplate\n",
    "from langchain_openai.chat_models import ChatOpenAI\n",
    "\n",
    "llm = ChatOpenAI(model=\"gpt-4o-mini\")\n",
    "prompt = ChatPromptTemplate.from_messages(\n",
    "    [\n",
    "        (\n",
    "            \"system\",\n",
    "            \"You are a helpful assistant for industrial tasks. When asked a question, determine if there are appropriate\"\n",
    "            \"tools that can be employed to answer the question with factual context.\",\n",
    "        ),\n",
    "        (\"placeholder\", \"{chat_history}\"),\n",
    "        (\"human\", \"{input}\"),\n",
    "        (\"placeholder\", \"{agent_scratchpad}\"),\n",
    "    ]\n",
    ")\n",
    "agent = create_tool_calling_agent(llm, tools, prompt)\n",
    "\n",
    "agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "71b4ae1f-c5a3-4269-9241-d11a3207d758",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "\u001b[1m> Entering new AgentExecutor chain...\u001b[0m\n",
      "\u001b[32;1m\u001b[1;3m\n",
      "Invoking: `AICatalog__AISchema__calculate_cutting_speed` with `{'material': 'steel', 'thickness': 0.00635, 'laser_power': 5000}`\n",
      "\n",
      "\n",
      "\u001b[0m\u001b[33;1m\u001b[1;3m{\"error\": \"calculate_cutting_speed() missing 1 required positional argument: 'laser_efficiency'\"}\u001b[0m\u001b[32;1m\u001b[1;3m\n",
      "Invoking: `AICatalog__AISchema__calculate_required_laser_power` with `{'material': 'steel', 'thickness': 0.00635, 'cutting_speed': 1}`\n",
      "\n",
      "\n",
      "\u001b[0m\u001b[36;1m\u001b[1;3m{\"error\": \"calculate_required_laser_power() missing 1 required positional argument: 'laser_efficiency'\"}\u001b[0m\u001b[32;1m\u001b[1;3m\n",
      "Invoking: `AICatalog__AISchema__calculate_cutting_speed` with `{'material': 'steel', 'thickness': 0.00635, 'laser_power': 5000, 'laser_efficiency': 0.8}`\n",
      "\n",
      "\n",
      "\u001b[0m\u001b[33;1m\u001b[1;3m{\"format\": \"SCALAR\", \"value\": \"6299.212598425197\"}\u001b[0m\u001b[32;1m\u001b[1;3m\n",
      "Invoking: `AICatalog__AISchema__calculate_required_laser_power` with `{'material': 'steel', 'thickness': 0.00635, 'cutting_speed': 1, 'laser_efficiency': 0.8}`\n",
      "\n",
      "\n",
      "\u001b[0m\u001b[36;1m\u001b[1;3m{\"format\": \"SCALAR\", \"value\": \"0.79375\"}\u001b[0m\u001b[32;1m\u001b[1;3mHere are the results for your sunroof project in the shipping container:\n",
      "\n",
      "1. **Maximum Cutting Speed**: With a 5 kW laser and assuming a laser efficiency of 80%, the maximum cutting speed you can achieve on 0.25 inch thick mild steel is approximately **6.30 meters per second**.\n",
      "\n",
      "2. **Required Laser Power for a Cutting Speed of 1 m/s**: To achieve a cutting speed of 1 meter per second, you would require approximately **0.79 kW (or 793.75 W)** of laser power.\n",
      "\n",
      "### Conclusion\n",
      "Since your 5 kW laser exceeds the required power to achieve a cutting speed of 1 m/s, you should be able to cut the sunroof in an afternoon, depending on the actual cutting path length and any additional setup time needed.\u001b[0m\n",
      "\n",
      "\u001b[1m> Finished chain.\u001b[0m\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "{'input': 'I want to make a sunroof in a shipping container. My friend has a 5 kw laser. The shipping container is made of 0.25inch thick mild steel and is a standard 40 foot ISO container. I want to see if I can get this done in an afternoon.',\n",
       " 'output': 'Here are the results for your sunroof project in the shipping container:\\n\\n1. **Maximum Cutting Speed**: With a 5 kW laser and assuming a laser efficiency of 80%, the maximum cutting speed you can achieve on 0.25 inch thick mild steel is approximately **6.30 meters per second**.\\n\\n2. **Required Laser Power for a Cutting Speed of 1 m/s**: To achieve a cutting speed of 1 meter per second, you would require approximately **0.79 kW (or 793.75 W)** of laser power.\\n\\n### Conclusion\\nSince your 5 kW laser exceeds the required power to achieve a cutting speed of 1 m/s, you should be able to cut the sunroof in an afternoon, depending on the actual cutting path length and any additional setup time needed.'}"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "agent_executor.invoke(\n",
    "    {\n",
    "        \"input\": \"I want to make a sunroof in a shipping container. My friend has a 5 kw laser. The shipping container is made \"\n",
    "        \"of 0.25inch thick mild steel and is a standard 40 foot ISO container. I want to see if I can get this done in an afternoon.\"\n",
    "    }\n",
    ")"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.9"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
